🎖️GitЯра🎖️
examples/simple_sensor/SensorMesh.cpp HEAD (0679dbef) Text, 35.05 KB
Tff7b72#Tff7b72include T8b949e"SensorMesh.h"
T8b949e/* ------------------------------ Config -------------------------------- */
Tff7b72#Tff7b72ifndef LORA_FREQ
Tff7b72#Tff7b72define LORA_FREQ 915.0
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef LORA_BW
Tff7b72#Tff7b72define LORA_BW 250
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef LORA_SF
Tff7b72#Tff7b72define LORA_SF 10
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef LORA_CR
Tff7b72#Tff7b72define LORA_CR 5
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef LORA_TX_POWER
Tff7b72#Tff7b72define LORA_TX_POWER 20
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef ADVERT_NAME
Tff7b72#Tff7b72define ADVERT_NAME "sensor"
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef ADVERT_LAT
Tff7b72#Tff7b72define ADVERT_LAT 0.0
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef ADVERT_LON
Tff7b72#Tff7b72define ADVERT_LON 0.0
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef ADMIN_PASSWORD
Tff7b72#Tff7b72define ADMIN_PASSWORD "password"
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef SERVER_RESPONSE_DELAY
Tff7b72#Tff7b72define SERVER_RESPONSE_DELAY 300
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef TXT_ACK_DELAY
Tff7b72#Tff7b72define TXT_ACK_DELAY 200
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifndef SENSOR_READ_INTERVAL_SECS
Tff7b72#Tff7b72define SENSOR_READ_INTERVAL_SECS 60
Tff7b72#Tff7b72endif
T8b949e/* ------------------------------ Code -------------------------------- */
Tff7b72#Tff7b72define FIRMWARE_VER_LEVEL 1
Tff7b72#Tff7b72define REQ_TYPE_LOGIN 0x00
Tff7b72#Tff7b72define REQ_TYPE_GET_STATUS 0x01
Tff7b72#Tff7b72define REQ_TYPE_KEEP_ALIVE 0x02
Tff7b72#Tff7b72define REQ_TYPE_GET_TELEMETRY_DATA 0x03
Tff7b72#Tff7b72define REQ_TYPE_GET_AVG_MIN_MAX 0x04
Tff7b72#Tff7b72define REQ_TYPE_GET_ACCESS_LIST 0x05
Tff7b72#Tff7b72define RESP_SERVER_LOGIN_OK 0 T8b949e// response to ANON_REQ
Tff7b72#Tff7b72define CLI_REPLY_DELAY_MILLIS 1000
Tff7b72#Tff7b72define LAZY_CONTACTS_WRITE_DELAY 5000
Tff7b72#Tff7b72define ALERT_ACK_EXPIRY_MILLIS 8000 T8b949e// wait 8 secs for ACKs to alert messages
Tff7b72static Te6edf3File Td2a8ffopenAppendTb4b4b4(Te6edf3FILESYSTEMTff7b72* Te6edf3_fsTb4b4b4, Tff7b72const Tffa657charTff7b72* Te6edf3fnameTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
Tff7b72return Te6edf3_fsTff7b72-Tff7b72>Te6edf3openTb4b4b4(Te6edf3fnameTb4b4b4, Te6edf3FILE_O_WRITETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(RP2040_PLATFORM)
Tff7b72return Te6edf3_fsTff7b72-Tff7b72>Te6edf3openTb4b4b4(Te6edf3fnameTb4b4b4, Ta5d6ff"Ta5d6ffaTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72return Te6edf3_fsTff7b72-Tff7b72>Te6edf3openTb4b4b4(Te6edf3fnameTb4b4b4, Ta5d6ff"Ta5d6ffaTa5d6ff"Tb4b4b4, Tffa657trueTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72static Tffa657uint8_t Td2a8ffgetDataSizeTb4b4b4(Tffa657uint8_t Te6edf3typeTb4b4b4) Tb4b4b4{
Tff7b72switch Tb4b4b4(Te6edf3typeTb4b4b4) Tb4b4b4{
Tff7b72case Tff7b72LPP_GPSTb4b4b4:
Tff7b72return T79c0ff9Tb4b4b4;
Tff7b72case Tff7b72LPP_POLYLINETb4b4b4:
Tff7b72return T79c0ff8Tb4b4b4; T8b949e// TODO: this is MINIMIUM
Tff7b72case Tff7b72LPP_GYROMETERTb4b4b4:
Tff7b72case Tff7b72LPP_ACCELEROMETERTb4b4b4:
Tff7b72return T79c0ff6Tb4b4b4;
Tff7b72case Tff7b72LPP_GENERIC_SENSORTb4b4b4:
Tff7b72case Tff7b72LPP_FREQUENCYTb4b4b4:
Tff7b72case Tff7b72LPP_DISTANCETb4b4b4:
Tff7b72case Tff7b72LPP_ENERGYTb4b4b4:
Tff7b72case Tff7b72LPP_UNIXTIMETb4b4b4:
Tff7b72return T79c0ff4Tb4b4b4;
Tff7b72case Tff7b72LPP_COLOURTb4b4b4:
Tff7b72return T79c0ff3Tb4b4b4;
Tff7b72case Tff7b72LPP_ANALOG_INPUTTb4b4b4:
Tff7b72case Tff7b72LPP_ANALOG_OUTPUTTb4b4b4:
Tff7b72case Tff7b72LPP_LUMINOSITYTb4b4b4:
Tff7b72case Tff7b72LPP_TEMPERATURETb4b4b4:
Tff7b72case Tff7b72LPP_CONCENTRATIONTb4b4b4:
Tff7b72case Tff7b72LPP_BAROMETRIC_PRESSURETb4b4b4:
Tff7b72case Tff7b72LPP_RELATIVE_HUMIDITYTb4b4b4:
Tff7b72case Tff7b72LPP_ALTITUDETb4b4b4:
Tff7b72case Tff7b72LPP_VOLTAGETb4b4b4:
Tff7b72case Tff7b72LPP_CURRENTTb4b4b4:
Tff7b72case Tff7b72LPP_DIRECTIONTb4b4b4:
Tff7b72case Tff7b72LPP_POWERTb4b4b4:
Tff7b72return T79c0ff2Tb4b4b4;
Tb4b4b4}
Tff7b72return T79c0ff1Tb4b4b4;
Tb4b4b4}
Tff7b72static Tffa657uint32_t Td2a8ffgetMultiplierTb4b4b4(Tffa657uint8_t Te6edf3typeTb4b4b4) Tb4b4b4{
Tff7b72switch Tb4b4b4(Te6edf3typeTb4b4b4) Tb4b4b4{
Tff7b72case Tff7b72LPP_CURRENTTb4b4b4:
Tff7b72case Tff7b72LPP_DISTANCETb4b4b4:
Tff7b72case Tff7b72LPP_ENERGYTb4b4b4:
Tff7b72return T79c0ff1000Tb4b4b4;
Tff7b72case Tff7b72LPP_VOLTAGETb4b4b4:
Tff7b72case Tff7b72LPP_ANALOG_INPUTTb4b4b4:
Tff7b72case Tff7b72LPP_ANALOG_OUTPUTTb4b4b4:
Tff7b72return T79c0ff100Tb4b4b4;
Tff7b72case Tff7b72LPP_TEMPERATURETb4b4b4:
Tff7b72case Tff7b72LPP_BAROMETRIC_PRESSURETb4b4b4:
Tff7b72case Tff7b72LPP_RELATIVE_HUMIDITYTb4b4b4:
Tff7b72return T79c0ff10Tb4b4b4;
Tb4b4b4}
Tff7b72return T79c0ff1Tb4b4b4;
Tb4b4b4}
Tff7b72static Tffa657bool Td2a8ffisSignedTb4b4b4(Tffa657uint8_t Te6edf3typeTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3type Tff7b72=Tff7b72= Te6edf3LPP_ALTITUDE Tff7b72|Tff7b72| Te6edf3type Tff7b72=Tff7b72= Te6edf3LPP_TEMPERATURE Tff7b72|Tff7b72| Te6edf3type Tff7b72=Tff7b72= Te6edf3LPP_GYROMETER Tff7b72|Tff7b72|
Te6edf3type Tff7b72=Tff7b72= Te6edf3LPP_ANALOG_INPUT Tff7b72|Tff7b72| Te6edf3type Tff7b72=Tff7b72= Te6edf3LPP_ANALOG_OUTPUT Tff7b72|Tff7b72| Te6edf3type Tff7b72=Tff7b72= Te6edf3LPP_GPS Tff7b72|Tff7b72| Te6edf3type Tff7b72=Tff7b72= Te6edf3LPP_ACCELEROMETERTb4b4b4;
Tb4b4b4}
Tff7b72static Tffa657float Td2a8ffgetFloatTb4b4b4(Tff7b72const Tffa657uint8_t Tff7b72* Te6edf3bufferTb4b4b4, Tffa657uint8_t Te6edf3sizeTb4b4b4, Tffa657uint32_t Te6edf3multiplierTb4b4b4, Tffa657bool Te6edf3is_signedTb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3value Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657uint8_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3sizeTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Te6edf3value Tff7b72= Tb4b4b4(Te6edf3value Tff7b72<Tff7b72< T79c0ff8Tb4b4b4) Tff7b72+ Te6edf3bufferTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Tb4b4b4}
Tffa657int Te6edf3sign Tff7b72= T79c0ff1Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3is_signedTb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3bit Tff7b72= T79c0ff1ul Tff7b72<Tff7b72< Tb4b4b4(Tb4b4b4(Te6edf3size Tff7b72* T79c0ff8Tb4b4b4) Tff7b72- T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tb4b4b4(Te6edf3value Tff7b72& Te6edf3bitTb4b4b4) Tff7b72=Tff7b72= Te6edf3bitTb4b4b4) Tb4b4b4{
Te6edf3value Tff7b72= Tb4b4b4(Te6edf3bit Tff7b72<Tff7b72< T79c0ff1Tb4b4b4) Tff7b72- Te6edf3valueTb4b4b4;
Te6edf3sign Tff7b72= T79c0ff-1Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3sign Tff7b72* Tb4b4b4(Tb4b4b4(Tffa657floatTb4b4b4) Te6edf3value Tff7b72/ Te6edf3multiplierTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72static Tffa657uint8_t Td2a8ffputFloatTb4b4b4(Tffa657uint8_t Tff7b72* Te6edf3destTb4b4b4, Tffa657float Te6edf3valueTb4b4b4, Tffa657uint8_t Te6edf3sizeTb4b4b4, Tffa657uint32_t Te6edf3multiplierTb4b4b4, Tffa657bool Te6edf3is_signedTb4b4b4) Tb4b4b4{
T8b949e// check sign
Tffa657bool Te6edf3sign Tff7b72= Te6edf3value Tff7b72< T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3signTb4b4b4) Te6edf3value Tff7b72= Tff7b72-Te6edf3valueTb4b4b4;
T8b949e// get value to store
Tffa657uint32_t Te6edf3v Tff7b72= Te6edf3value Tff7b72* Te6edf3multiplierTb4b4b4;
T8b949e// format an uint32_t as if it was an int32_t
Tff7b72if Tb4b4b4(Te6edf3is_signed Tff7b72& Te6edf3signTb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3mask Tff7b72= Tb4b4b4(T79c0ff1 Tff7b72<Tff7b72< Tb4b4b4(Te6edf3size Tff7b72* T79c0ff8Tb4b4b4)Tb4b4b4) Tff7b72- T79c0ff1Tb4b4b4;
Te6edf3v Tff7b72= Te6edf3v Tff7b72& Te6edf3maskTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3signTb4b4b4) Te6edf3v Tff7b72= Te6edf3mask Tff7b72- Te6edf3v Tff7b72+ T79c0ff1Tb4b4b4;
Tb4b4b4}
T8b949e// add bytes (MSB first)
Tff7b72for Tb4b4b4(Tffa657uint8_t Te6edf3iTff7b72=T79c0ff1Tb4b4b4; Te6edf3iTff7b72<Tff7b72=Te6edf3sizeTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Te6edf3destTb4b4b4[Te6edf3size Tff7b72- Te6edf3iTb4b4b4] Tff7b72= Tb4b4b4(Te6edf3v Tff7b72& T79c0ff0xFFTb4b4b4)Tb4b4b4;
Te6edf3v Tff7b72>Tff7b72>Tff7b72= T79c0ff8Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3sizeTb4b4b4;
Tb4b4b4}
Tffa657uint8_t Td2a8ffSensorMesh::handleRequestTb4b4b4(Tffa657uint8_t Te6edf3permsTb4b4b4, Tffa657uint32_t Te6edf3sender_timestampTb4b4b4, Tffa657uint8_t Te6edf3req_typeTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3payloadTb4b4b4, Tffa657size_t Te6edf3payload_lenTb4b4b4) Tb4b4b4{
Te6edf3memcpyTb4b4b4(Te6edf3reply_dataTb4b4b4, Tff7b72&Te6edf3sender_timestampTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// reflect sender_timestamp back in response packet (kind of like a 'tag')
Tff7b72if Tb4b4b4(Te6edf3req_type Tff7b72=Tff7b72= Te6edf3REQ_TYPE_GET_TELEMETRY_DATATb4b4b4) Tb4b4b4{ T8b949e// allow all
Tffa657uint8_t Te6edf3perm_mask Tff7b72= Tff7b72~Tb4b4b4(Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4; T8b949e// NEW: first reserved byte (of 4), is now inverse mask to apply to permissions
Te6edf3telemetryTb4b4b4.Te6edf3resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3telemetryTb4b4b4.Te6edf3addVoltageTb4b4b4(Te6edf3TELEM_CHANNEL_SELFTb4b4b4, Tb4b4b4(Tffa657floatTb4b4b4)Te6edf3boardTb4b4b4.Te6edf3getBattMilliVoltsTb4b4b4(Tb4b4b4) Tff7b72/ T79c0ff1000.0fTb4b4b4)Tb4b4b4;
T8b949e// query other sensors -- target specific
Te6edf3sensorsTb4b4b4.Te6edf3querySensorsTb4b4b4(T79c0ff0xFF Tff7b72& Te6edf3perm_maskTb4b4b4, Te6edf3telemetryTb4b4b4)Tb4b4b4; T8b949e// allow all telemetry permissions for admin or guest
T8b949e// TODO: let requester know permissions they have: telemetry.addPresence(TELEM_CHANNEL_SELF, perms);
Tffa657uint8_t Te6edf3tlen Tff7b72= Te6edf3telemetryTb4b4b4.Te6edf3getSizeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Te6edf3telemetryTb4b4b4.Te6edf3getBufferTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3tlenTb4b4b4)Tb4b4b4;
Tff7b72return T79c0ff4 Tff7b72+ Te6edf3tlenTb4b4b4; T8b949e// reply_len
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3req_type Tff7b72=Tff7b72= Te6edf3REQ_TYPE_GET_AVG_MIN_MAX Tff7b72&Tff7b72& Tb4b4b4(Te6edf3perms Tff7b72& Te6edf3PERM_ACL_ROLE_MASKTb4b4b4) Tff7b72>Tff7b72= Te6edf3PERM_ACL_READ_ONLYTb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3start_secs_agoTb4b4b4, Te6edf3end_secs_agoTb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3start_secs_agoTb4b4b4, Tff7b72&Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3end_secs_agoTb4b4b4, Tff7b72&Te6edf3payloadTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4;
Tffa657uint8_t Te6edf3res1 Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff8Tb4b4b4]Tb4b4b4; T8b949e// reserved for future (extra query params)
Tffa657uint8_t Te6edf3res2 Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff9Tb4b4b4]Tb4b4b4;
Te6edf3MinMaxAvg Te6edf3dataTb4b4b4[T79c0ff8Tb4b4b4]Tb4b4b4;
Tffa657int Te6edf3nTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3res1 Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3res2 Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3n Tff7b72= Te6edf3querySeriesDataTb4b4b4(Te6edf3start_secs_agoTb4b4b4, Te6edf3end_secs_agoTb4b4b4, Te6edf3dataTb4b4b4, T79c0ff8Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3n Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tffa657uint8_t Te6edf3ofs Tff7b72= T79c0ff4Tb4b4b4;
Tb4b4b4{
Tffa657uint32_t Te6edf3now Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[Te6edf3ofsTb4b4b4]Tb4b4b4, Tff7b72&Te6edf3nowTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; Te6edf3ofs Tff7b72+Tff7b72= T79c0ff4Tb4b4b4;
Tb4b4b4}
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3nTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3d Tff7b72= Tff7b72&Te6edf3dataTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Te6edf3reply_dataTb4b4b4[Te6edf3ofsTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3dTff7b72-Tff7b72>Te6edf3_channelTb4b4b4;
Te6edf3reply_dataTb4b4b4[Te6edf3ofsTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3dTff7b72-Tff7b72>Te6edf3_lpp_typeTb4b4b4;
Tffa657uint8_t Te6edf3sz Tff7b72= Te6edf3getDataSizeTb4b4b4(Te6edf3dTff7b72-Tff7b72>Te6edf3_lpp_typeTb4b4b4)Tb4b4b4;
Tffa657uint32_t Te6edf3mult Tff7b72= Te6edf3getMultiplierTb4b4b4(Te6edf3dTff7b72-Tff7b72>Te6edf3_lpp_typeTb4b4b4)Tb4b4b4;
Tffa657bool Te6edf3is_signed Tff7b72= Te6edf3isSignedTb4b4b4(Te6edf3dTff7b72-Tff7b72>Te6edf3_lpp_typeTb4b4b4)Tb4b4b4;
Te6edf3ofs Tff7b72+Tff7b72= Te6edf3putFloatTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[Te6edf3ofsTb4b4b4]Tb4b4b4, Te6edf3dTff7b72-Tff7b72>Te6edf3_minTb4b4b4, Te6edf3szTb4b4b4, Te6edf3multTb4b4b4, Te6edf3is_signedTb4b4b4)Tb4b4b4;
Te6edf3ofs Tff7b72+Tff7b72= Te6edf3putFloatTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[Te6edf3ofsTb4b4b4]Tb4b4b4, Te6edf3dTff7b72-Tff7b72>Te6edf3_maxTb4b4b4, Te6edf3szTb4b4b4, Te6edf3multTb4b4b4, Te6edf3is_signedTb4b4b4)Tb4b4b4;
Te6edf3ofs Tff7b72+Tff7b72= Te6edf3putFloatTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[Te6edf3ofsTb4b4b4]Tb4b4b4, Te6edf3dTff7b72-Tff7b72>Te6edf3_avgTb4b4b4, Te6edf3szTb4b4b4, Te6edf3multTb4b4b4, Te6edf3is_signedTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3ofsTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3req_type Tff7b72=Tff7b72= Te6edf3REQ_TYPE_GET_ACCESS_LIST Tff7b72&Tff7b72& Tb4b4b4(Te6edf3perms Tff7b72& Te6edf3PERM_ACL_ROLE_MASKTb4b4b4) Tff7b72=Tff7b72= Te6edf3PERM_ACL_ADMINTb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3res1 Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4; T8b949e// reserved for future (extra query params)
Tffa657uint8_t Te6edf3res2 Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3res1 Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3res2 Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3ofs Tff7b72= T79c0ff4Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3ofs Tff7b72+ T79c0ff7 Tff7b72<Tff7b72= Tff7b72sizeofTb4b4b4(Te6edf3reply_dataTb4b4b4) Tff7b72- T79c0ff4Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3c Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cTff7b72-Tff7b72>Te6edf3permissions Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72continueTb4b4b4; T8b949e// skip deleted entries
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[Te6edf3ofsTb4b4b4]Tb4b4b4, Te6edf3cTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4, T79c0ff6Tb4b4b4)Tb4b4b4; Te6edf3ofs Tff7b72+Tff7b72= T79c0ff6Tb4b4b4; T8b949e// just 6-byte pub_key prefix
Te6edf3reply_dataTb4b4b4[Te6edf3ofsTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3cTff7b72-Tff7b72>Te6edf3permissionsTb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3ofsTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return T79c0ff0Tb4b4b4; T8b949e// unknown command
Tb4b4b4}
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Td2a8ffSensorMesh::createSelfAdvertTb4b4b4(Tb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3app_dataTb4b4b4[Te6edf3MAX_ADVERT_DATA_SIZETb4b4b4]Tb4b4b4;
Tffa657uint8_t Te6edf3app_data_len Tff7b72= Te6edf3_cliTb4b4b4.Te6edf3buildAdvertDataTb4b4b4(Te6edf3ADV_TYPE_SENSORTb4b4b4, Te6edf3app_dataTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3createAdvertTb4b4b4(Te6edf3self_idTb4b4b4, Te6edf3app_dataTb4b4b4, Te6edf3app_data_lenTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657void Td2a8ffSensorMesh::sendAlertTb4b4b4(Tff7b72const Te6edf3ClientInfoTff7b72* Te6edf3cTb4b4b4, Te6edf3TriggerTff7b72* Te6edf3tTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3text_len Tff7b72= Te6edf3strlenTb4b4b4(Te6edf3tTff7b72-Tff7b72>Te6edf3textTb4b4b4)Tb4b4b4;
Tffa657uint8_t Te6edf3dataTb4b4b4[Te6edf3MAX_PACKET_PAYLOADTb4b4b4]Tb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3dataTb4b4b4, Tff7b72&Te6edf3tTff7b72-Tff7b72>Te6edf3timestampTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4;
Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72= Tb4b4b4(Te6edf3TXT_TYPE_PLAIN Tff7b72<Tff7b72< T79c0ff2Tb4b4b4) Tff7b72| Te6edf3tTff7b72-Tff7b72>Te6edf3attemptTb4b4b4; T8b949e// attempt and flags
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3dataTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4, Te6edf3tTff7b72-Tff7b72>Te6edf3textTb4b4b4, Te6edf3text_lenTb4b4b4)Tb4b4b4;
T8b949e// calc expected ACK reply
Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3sha256Tb4b4b4(Tb4b4b4(Tffa657uint8_t Tff7b72*Tb4b4b4)Tff7b72&Te6edf3tTff7b72-Tff7b72>Te6edf3expected_acksTb4b4b4[Te6edf3tTff7b72-Tff7b72>Te6edf3attemptTb4b4b4]Tb4b4b4, T79c0ff4Tb4b4b4, Te6edf3dataTb4b4b4, T79c0ff5 Tff7b72+ Te6edf3text_lenTb4b4b4, Te6edf3self_idTb4b4b4.Te6edf3pub_keyTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Te6edf3tTff7b72-Tff7b72>Te6edf3attemptTff7b72+Tff7b72+Tb4b4b4;
Tff7b72auto Te6edf3pkt Tff7b72= Te6edf3createDatagramTb4b4b4(Te6edf3PAYLOAD_TYPE_TXT_MSGTb4b4b4, Te6edf3cTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3cTff7b72-Tff7b72>Te6edf3shared_secretTb4b4b4, Te6edf3dataTb4b4b4, T79c0ff5 Tff7b72+ Te6edf3text_lenTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pktTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3cTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72!Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4) Tb4b4b4{ T8b949e// we have an out_path, so send DIRECT
Te6edf3sendDirectTb4b4b4(Te6edf3pktTb4b4b4, Te6edf3cTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3cTff7b72-Tff7b72>Te6edf3out_path_lenTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tffa657unsigned Tffa657long Te6edf3delay_millis Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3sendFloodTb4b4b4(Te6edf3pktTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3path_hash_mode Tff7b72+ T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Te6edf3tTff7b72-Tff7b72>Te6edf3send_expiry Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3ALERT_ACK_EXPIRY_MILLISTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657void Td2a8ffSensorMesh::alertIfTb4b4b4(Tffa657bool Te6edf3conditionTb4b4b4, Te6edf3TriggerTff7b72& Te6edf3tTb4b4b4, Te6edf3AlertPriority Te6edf3priTb4b4b4, Tff7b72const Tffa657charTff7b72* Te6edf3textTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3conditionTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3tTb4b4b4.Te6edf3isTriggeredTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3num_alert_tasks Tff7b72< Te6edf3MAX_CONCURRENT_ALERTSTb4b4b4) Tb4b4b4{
Te6edf3StrHelperTff7b72:Tff7b72:Te6edf3strncpyTb4b4b4(Te6edf3tTb4b4b4.Te6edf3textTb4b4b4, Te6edf3textTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3tTb4b4b4.Te6edf3textTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3tTb4b4b4.Te6edf3pri Tff7b72= Te6edf3priTb4b4b4;
Te6edf3tTb4b4b4.Te6edf3send_expiry Tff7b72= T79c0ff0Tb4b4b4; T8b949e// signal that initial send is needed
Te6edf3tTb4b4b4.Te6edf3attempt Tff7b72= T79c0ff4Tb4b4b4;
Te6edf3tTb4b4b4.Te6edf3curr_contact_idx Tff7b72= T79c0ff-1Tb4b4b4; T8b949e// start iterating thru contacts[]
Te6edf3alert_tasksTb4b4b4[Te6edf3num_alert_tasksTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Tff7b72&Te6edf3tTb4b4b4; T8b949e// add to queue
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3tTb4b4b4.Te6edf3isTriggeredTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3tTb4b4b4.Te6edf3textTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4;
T8b949e// remove 't' from alert queue
Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3i Tff7b72< Te6edf3num_alert_tasks Tff7b72&Tff7b72& Te6edf3alert_tasksTb4b4b4[Te6edf3iTb4b4b4] Tff7b72!Tff7b72= Tff7b72&Te6edf3tTb4b4b4) Te6edf3iTff7b72+Tff7b72+Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3i Tff7b72< Te6edf3num_alert_tasksTb4b4b4) Tb4b4b4{ T8b949e// found, now delete from array
Te6edf3num_alert_tasksTff7b72-Tff7b72-Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3i Tff7b72< Te6edf3num_alert_tasksTb4b4b4) Tb4b4b4{
Te6edf3alert_tasksTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Te6edf3alert_tasksTb4b4b4[Te6edf3i Tff7b72+ T79c0ff1Tb4b4b4]Tb4b4b4;
Te6edf3iTff7b72+Tff7b72+Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tffa657float Td2a8ffSensorMesh::getAirtimeBudgetFactorTb4b4b4(Tb4b4b4) Tff7b72const Tb4b4b4{
Tff7b72return Te6edf3_prefsTb4b4b4.Te6edf3airtime_factorTb4b4b4;
Tb4b4b4}
Tffa657bool Td2a8ffSensorMesh::allowPacketForwardTb4b4b4(Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3disable_fwdTb4b4b4) Tff7b72return Tffa657falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3isRouteFloodTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashCountTb4b4b4(Tb4b4b4) Tff7b72>Tff7b72= Te6edf3_prefsTb4b4b4.Te6edf3flood_maxTb4b4b4) Tff7b72return Tffa657falseTb4b4b4;
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}
Tffa657int Td2a8ffSensorMesh::calcRxDelayTb4b4b4(Tffa657float Te6edf3scoreTb4b4b4, Tffa657uint32_t Te6edf3air_timeTb4b4b4) Tff7b72const Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3rx_delay_base Tff7b72<Tff7b72= T79c0ff0.0fTb4b4b4) Tff7b72return T79c0ff0Tb4b4b4;
Tff7b72return Tb4b4b4(Tffa657intTb4b4b4) Tb4b4b4(Tb4b4b4(Te6edf3powTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3rx_delay_baseTb4b4b4, T79c0ff0.85f Tff7b72- Te6edf3scoreTb4b4b4) Tff7b72- T79c0ff1.0Tb4b4b4) Tff7b72* Te6edf3air_timeTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657uint32_t Td2a8ffSensorMesh::getRetransmitDelayTb4b4b4(Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3t Tff7b72= Tb4b4b4(Te6edf3_radioTff7b72-Tff7b72>Te6edf3getEstAirtimeForTb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathByteLenTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3packetTff7b72-Tff7b72>Te6edf3payload_len Tff7b72+ T79c0ff2Tb4b4b4) Tff7b72* Te6edf3_prefsTb4b4b4.Te6edf3tx_delay_factorTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3getRNGTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3nextIntTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff6Tb4b4b4)Tff7b72*Te6edf3tTb4b4b4;
Tb4b4b4}
Tffa657uint32_t Td2a8ffSensorMesh::getDirectRetransmitDelayTb4b4b4(Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3t Tff7b72= Tb4b4b4(Te6edf3_radioTff7b72-Tff7b72>Te6edf3getEstAirtimeForTb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathByteLenTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3packetTff7b72-Tff7b72>Te6edf3payload_len Tff7b72+ T79c0ff2Tb4b4b4) Tff7b72* Te6edf3_prefsTb4b4b4.Te6edf3direct_tx_delay_factorTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3getRNGTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3nextIntTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff6Tb4b4b4)Tff7b72*Te6edf3tTb4b4b4;
Tb4b4b4}
Tffa657int Td2a8ffSensorMesh::getInterferenceThresholdTb4b4b4(Tb4b4b4) Tff7b72const Tb4b4b4{
Tff7b72return Te6edf3_prefsTb4b4b4.Te6edf3interference_thresholdTb4b4b4;
Tb4b4b4}
Tffa657bool Td2a8ffSensorMesh::getCADEnabledTb4b4b4(Tb4b4b4) Tff7b72const Tb4b4b4{
Tff7b72return Te6edf3_prefsTb4b4b4.Te6edf3cad_enabledTb4b4b4;
Tb4b4b4}
Tffa657int Td2a8ffSensorMesh::getAGCResetIntervalTb4b4b4(Tb4b4b4) Tff7b72const Tb4b4b4{
Tff7b72return Tb4b4b4(Tb4b4b4(Tffa657intTb4b4b4)Te6edf3_prefsTb4b4b4.Te6edf3agc_reset_intervalTb4b4b4) Tff7b72* T79c0ff4000Tb4b4b4; T8b949e// milliseconds
Tb4b4b4}
Tffa657uint8_t Td2a8ffSensorMesh::handleLoginReqTb4b4b4(Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3IdentityTff7b72& Te6edf3senderTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tffa657uint32_t Te6edf3sender_timestampTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657bool Te6edf3is_floodTb4b4b4) Tb4b4b4{
Te6edf3ClientInfoTff7b72* Te6edf3clientTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3dataTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// blank password, just check if sender is in ACL
Te6edf3client Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientTb4b4b4(Te6edf3senderTb4b4b4.Te6edf3pub_keyTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3client Tff7b72=Tff7b72= Tffa657NULLTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MESH_DEBUG
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffLogin, sender not in ACLTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72return T79c0ff0Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3strcmpTb4b4b4(Tb4b4b4(Tffa657char Tff7b72*Tb4b4b4) Te6edf3dataTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3passwordTb4b4b4) Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// check for valid admin password
Tff7b72#Tff7b72if MESH_DEBUG
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffInvalid password: %sTa5d6ff"Tb4b4b4, Tff7b72&Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72return T79c0ff0Tb4b4b4;
Tb4b4b4}
Te6edf3client Tff7b72= Te6edf3aclTb4b4b4.Te6edf3putClientTb4b4b4(Te6edf3senderTb4b4b4, Te6edf3PERM_RECV_ALERTS_HI Tff7b72| Te6edf3PERM_RECV_ALERTS_LOTb4b4b4)Tb4b4b4; T8b949e// add to contacts (if not already known)
Tff7b72if Tb4b4b4(Te6edf3sender_timestamp Tff7b72<Tff7b72= Te6edf3clientTff7b72-Tff7b72>Te6edf3last_timestampTb4b4b4) Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffPossible login replay attack!Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return T79c0ff0Tb4b4b4; T8b949e// FATAL: client table is full -OR- replay attack
Tb4b4b4}
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffLogin success!Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3last_timestamp Tff7b72= Te6edf3sender_timestampTb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3last_activity Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3permissions Tff7b72|Tff7b72= Te6edf3PERM_ACL_ADMINTb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3shared_secretTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Te6edf3dirty_contacts_expiry Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3LAZY_CONTACTS_WRITE_DELAYTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3is_floodTb4b4b4) Tb4b4b4{
Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4; T8b949e// need to rediscover out_path
Tb4b4b4}
Tffa657uint32_t Te6edf3now Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeUniqueTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3reply_dataTb4b4b4, Tff7b72&Te6edf3nowTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// response packets always prefixed with timestamp
Te6edf3reply_dataTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72= Te6edf3RESP_SERVER_LOGIN_OKTb4b4b4;
Te6edf3reply_dataTb4b4b4[T79c0ff5Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3reply_dataTb4b4b4[T79c0ff6Tb4b4b4] Tff7b72= Te6edf3clientTff7b72-Tff7b72>Te6edf3isAdminTb4b4b4(Tb4b4b4) Tff7b72? T79c0ff1 Tff7b72: T79c0ff0Tb4b4b4;
Te6edf3reply_dataTb4b4b4[T79c0ff7Tb4b4b4] Tff7b72= Te6edf3clientTff7b72-Tff7b72>Te6edf3permissionsTb4b4b4;
Te6edf3getRNGTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3randomTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[T79c0ff8Tb4b4b4]Tb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// random blob to help packet-hash uniqueness
Te6edf3reply_dataTb4b4b4[T79c0ff12Tb4b4b4] Tff7b72= Te6edf3FIRMWARE_VER_LEVELTb4b4b4;
Tff7b72return T79c0ff13Tb4b4b4; T8b949e// reply length
Tb4b4b4}
Tffa657void Td2a8ffSensorMesh::handleCommandTb4b4b4(Tffa657uint32_t Te6edf3sender_timestampTb4b4b4, Tffa657charTff7b72* Te6edf3commandTb4b4b4, Tffa657charTff7b72* Te6edf3replyTb4b4b4) Tb4b4b4{
Tff7b72while Tb4b4b4(Tff7b72*Te6edf3command Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4) Te6edf3commandTff7b72+Tff7b72+Tb4b4b4; T8b949e// skip leading spaces
Tff7b72if Tb4b4b4(Te6edf3strlenTb4b4b4(Te6edf3commandTb4b4b4) Tff7b72> T79c0ff4 Tff7b72&Tff7b72& Te6edf3commandTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff|Ta5d6ff'Tb4b4b4) Tb4b4b4{ T8b949e// optional prefix (for companion radio CLI)
Te6edf3memcpyTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3commandTb4b4b4, T79c0ff3Tb4b4b4)Tb4b4b4; T8b949e// reflect the prefix back
Te6edf3reply Tff7b72+Tff7b72= T79c0ff3Tb4b4b4;
Te6edf3command Tff7b72+Tff7b72= T79c0ff3Tb4b4b4;
Tb4b4b4}
T8b949e// first, see if this is a custom-handled CLI command (ie. in main.cpp)
Tff7b72if Tb4b4b4(Te6edf3handleCustomCommandTb4b4b4(Te6edf3sender_timestampTb4b4b4, Te6edf3commandTb4b4b4, Te6edf3replyTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4; T8b949e// command has been handled
Tb4b4b4}
T8b949e// handle sensor-specific CLI commands
Tff7b72if Tb4b4b4(Te6edf3memcmpTb4b4b4(Te6edf3commandTb4b4b4, Ta5d6ff"Ta5d6ffsetperm Ta5d6ff"Tb4b4b4, T79c0ff8Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// format: setperm {pubkey-hex} {permissions-int8}
Tffa657charTff7b72* Te6edf3hex Tff7b72= Tff7b72&Te6edf3commandTb4b4b4[T79c0ff8Tb4b4b4]Tb4b4b4;
Tffa657charTff7b72* Te6edf3sp Tff7b72= Te6edf3strchrTb4b4b4(Te6edf3hexTb4b4b4, Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4)Tb4b4b4; T8b949e// look for separator char
Tff7b72if Tb4b4b4(Te6edf3sp Tff7b72=Tff7b72= Tffa657NULLTb4b4b4) Tb4b4b4{
Te6edf3strcpyTb4b4b4(Te6edf3replyTb4b4b4, Ta5d6ff"Ta5d6ffErr - bad paramsTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72*Te6edf3spTff7b72+Tff7b72+ Tff7b72= T79c0ff0Tb4b4b4; T8b949e// replace space with null terminator
Tffa657uint8_t Te6edf3pubkeyTb4b4b4[Te6edf3PUB_KEY_SIZETb4b4b4]Tb4b4b4;
Tffa657int Te6edf3hex_len Tff7b72= Te6edf3minTb4b4b4(Te6edf3sp Tff7b72- Te6edf3hexTb4b4b4, Te6edf3PUB_KEY_SIZETff7b72*T79c0ff2Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3fromHexTb4b4b4(Te6edf3pubkeyTb4b4b4, Te6edf3hex_len Tff7b72/ T79c0ff2Tb4b4b4, Te6edf3hexTb4b4b4)Tb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3perms Tff7b72= Te6edf3atoiTb4b4b4(Te6edf3spTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3aclTb4b4b4.Te6edf3applyPermissionsTb4b4b4(Te6edf3self_idTb4b4b4, Te6edf3pubkeyTb4b4b4, Te6edf3hex_len Tff7b72/ T79c0ff2Tb4b4b4, Te6edf3permsTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3dirty_contacts_expiry Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3LAZY_CONTACTS_WRITE_DELAYTb4b4b4)Tb4b4b4; T8b949e// trigger acl.save()
Te6edf3strcpyTb4b4b4(Te6edf3replyTb4b4b4, Ta5d6ff"Ta5d6ffOKTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3strcpyTb4b4b4(Te6edf3replyTb4b4b4, Ta5d6ff"Ta5d6ffErr - invalid paramsTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3strcpyTb4b4b4(Te6edf3replyTb4b4b4, Ta5d6ff"Ta5d6ffErr - bad pubkeyTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sender_timestamp Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3strcmpTb4b4b4(Te6edf3commandTb4b4b4, Ta5d6ff"Ta5d6ffget aclTa5d6ff"Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ffACL:Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3c Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cTff7b72-Tff7b72>Te6edf3permissions Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72continueTb4b4b4; T8b949e// skip deleted entries
Te6edf3SerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff%02X Ta5d6ff"Tb4b4b4, Te6edf3cTff7b72-Tff7b72>Te6edf3permissionsTb4b4b4)Tb4b4b4;
Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3printHexTb4b4b4(Te6edf3SerialTb4b4b4, Te6edf3cTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3replyTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3memcmpTb4b4b4(Te6edf3commandTb4b4b4, Ta5d6ff"Ta5d6ffio Ta5d6ff"Tb4b4b4, T79c0ff2Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// io {value}: write, io: read
Tff7b72if Tb4b4b4(Te6edf3commandTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4) Tb4b4b4{ T8b949e// it's a write
Tffa657uint32_t Te6edf3valTb4b4b4;
Tffa657uint32_t Te6edf3g Tff7b72= Te6edf3boardTb4b4b4.Te6edf3getGpioTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3commandTb4b4b4[T79c0ff3Tb4b4b4] Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ffrTa5d6ff'Tb4b4b4) Tb4b4b4{ T8b949e// reset bits
Te6edf3sscanfTb4b4b4(Tff7b72&Te6edf3commandTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ff%xTa5d6ff"Tb4b4b4, Tff7b72&Te6edf3valTb4b4b4)Tb4b4b4;
Te6edf3val Tff7b72= Te6edf3g Tff7b72& Tff7b72~Te6edf3valTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3commandTb4b4b4[T79c0ff3Tb4b4b4] Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ffsTa5d6ff'Tb4b4b4) Tb4b4b4{ T8b949e// set bits
Te6edf3sscanfTb4b4b4(Tff7b72&Te6edf3commandTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ff%xTa5d6ff"Tb4b4b4, Tff7b72&Te6edf3valTb4b4b4)Tb4b4b4;
Te6edf3val Tff7b72|Tff7b72= Te6edf3gTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3commandTb4b4b4[T79c0ff3Tb4b4b4] Tff7b72=Tff7b72= Ta5d6ff'Ta5d6fftTa5d6ff'Tb4b4b4) Tb4b4b4{ T8b949e// toggle bits
Te6edf3sscanfTb4b4b4(Tff7b72&Te6edf3commandTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ff%xTa5d6ff"Tb4b4b4, Tff7b72&Te6edf3valTb4b4b4)Tb4b4b4;
Te6edf3val Tff7b72^Tff7b72= Te6edf3gTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{ T8b949e// set value
Te6edf3sscanfTb4b4b4(Tff7b72&Te6edf3commandTb4b4b4[T79c0ff3Tb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ff%xTa5d6ff"Tb4b4b4, Tff7b72&Te6edf3valTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3boardTb4b4b4.Te6edf3setGpioTb4b4b4(Te6edf3valTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3sprintfTb4b4b4(Te6edf3replyTb4b4b4, Ta5d6ff"Ta5d6ff%xTa5d6ff"Tb4b4b4, Te6edf3boardTb4b4b4.Te6edf3getGpioTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72elseTb4b4b4{
Te6edf3_cliTb4b4b4.Te6edf3handleCommandTb4b4b4(Te6edf3sender_timestampTb4b4b4, Te6edf3commandTb4b4b4, Te6edf3replyTb4b4b4)Tb4b4b4; T8b949e// common CLI commands
Tb4b4b4}
Tb4b4b4}
Tffa657void Td2a8ffSensorMesh::onAnonDataRecvTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3IdentityTff7b72& Te6edf3senderTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_ANON_REQTb4b4b4) Tb4b4b4{ T8b949e// received an initial request by a possible admin client (unknown at this stage)
Tffa657uint32_t Te6edf3timestampTb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3timestampTb4b4b4, Te6edf3dataTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4;
Te6edf3dataTb4b4b4[Te6edf3lenTb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; T8b949e// ensure null terminator
Tffa657uint8_t Te6edf3reply_lenTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72=Tff7b72= T79c0ff0 Tff7b72|Tff7b72| Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72>Tff7b72= Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4) Tb4b4b4{ T8b949e// is password, ie. a login request
Te6edf3reply_len Tff7b72= Te6edf3handleLoginReqTb4b4b4(Te6edf3senderTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3timestampTb4b4b4, Tff7b72&Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3isRouteFloodTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
T8b949e//} else if (data[4] == ANON_REQ_TYPE_*) { // future type codes
T8b949e// TODO
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3reply_len Tff7b72= T79c0ff0Tb4b4b4; T8b949e// unknown request type
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3reply_len Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72returnTb4b4b4; T8b949e// invalid request
Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3isRouteFloodTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3path Tff7b72= Te6edf3createPathReturnTb4b4b4(Te6edf3senderTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3pathTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3path_lenTb4b4b4,
Te6edf3PAYLOAD_TYPE_RESPONSETb4b4b4, Te6edf3reply_dataTb4b4b4, Te6edf3reply_lenTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pathTb4b4b4) Te6edf3sendFloodTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3reply Tff7b72= Te6edf3createDatagramTb4b4b4(Te6edf3PAYLOAD_TYPE_RESPONSETb4b4b4, Te6edf3senderTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3reply_dataTb4b4b4, Te6edf3reply_lenTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3replyTb4b4b4) Te6edf3sendFloodTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tffa657int Td2a8ffSensorMesh::searchPeersByHashTb4b4b4(Tff7b72const Tffa657uint8_tTff7b72* Te6edf3hashTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3n Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3n Tff7b72< Te6edf3MAX_SEARCH_RESULTSTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3isHashMatchTb4b4b4(Te6edf3hashTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3matching_peer_indexesTb4b4b4[Te6edf3nTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3iTb4b4b4; T8b949e// store the INDEXES of matching contacts (for subsequent 'peer' methods)
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3nTb4b4b4;
Tb4b4b4}
Tffa657void Td2a8ffSensorMesh::getPeerSharedSecretTb4b4b4(Tffa657uint8_tTff7b72* Te6edf3dest_secretTb4b4b4, Tffa657int Te6edf3peer_idxTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3i Tff7b72= Te6edf3matching_peer_indexesTb4b4b4[Te6edf3peer_idxTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3i Tff7b72>Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// lookup pre-calculated shared_secret
Te6edf3memcpyTb4b4b4(Te6edf3dest_secretTb4b4b4, Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tff7b72-Tff7b72>Te6edf3shared_secretTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffgetPeerSharedSecret: Invalid peer idx: %dTa5d6ff"Tb4b4b4, Te6edf3iTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tffa657void Td2a8ffSensorMesh::sendAckToTb4b4b4(Tff7b72const Te6edf3ClientInfoTff7b72& Te6edf3destTb4b4b4, Tffa657uint32_t Te6edf3ack_hashTb4b4b4, Tffa657uint8_t Te6edf3path_hash_sizeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3destTb4b4b4.Te6edf3out_path_len Tff7b72=Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3ack Tff7b72= Te6edf3createAckTb4b4b4(Te6edf3ack_hashTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3ackTb4b4b4) Te6edf3sendFloodTb4b4b4(Te6edf3ackTb4b4b4, Te6edf3TXT_ACK_DELAYTb4b4b4, Te6edf3path_hash_sizeTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tffa657uint32_t Te6edf3d Tff7b72= Te6edf3TXT_ACK_DELAYTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3getExtraAckTransmitCountTb4b4b4(Tb4b4b4) Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3a1 Tff7b72= Te6edf3createMultiAckTb4b4b4(Te6edf3ack_hashTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3a1Tb4b4b4) Te6edf3sendDirectTb4b4b4(Te6edf3a1Tb4b4b4, Te6edf3destTb4b4b4.Te6edf3out_pathTb4b4b4, Te6edf3destTb4b4b4.Te6edf3out_path_lenTb4b4b4, Te6edf3dTb4b4b4)Tb4b4b4;
Te6edf3d Tff7b72+Tff7b72= T79c0ff300Tb4b4b4;
Tb4b4b4}
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3a2 Tff7b72= Te6edf3createAckTb4b4b4(Te6edf3ack_hashTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3a2Tb4b4b4) Te6edf3sendDirectTb4b4b4(Te6edf3a2Tb4b4b4, Te6edf3destTb4b4b4.Te6edf3out_pathTb4b4b4, Te6edf3destTb4b4b4.Te6edf3out_path_lenTb4b4b4, Te6edf3dTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tffa657void Td2a8ffSensorMesh::onPeerDataRecvTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint8_t Te6edf3typeTb4b4b4, Tffa657int Te6edf3sender_idxTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3i Tff7b72= Te6edf3matching_peer_indexesTb4b4b4[Te6edf3sender_idxTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3i Tff7b72< T79c0ff0 Tff7b72|Tff7b72| Te6edf3i Tff7b72>Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffonPeerDataRecv: Invalid sender idx: %dTa5d6ff"Tb4b4b4, Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3ClientInfoTff7b72* Te6edf3from Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3type Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_REQTb4b4b4) Tb4b4b4{ T8b949e// request (from a known contact)
Tffa657uint32_t Te6edf3timestampTb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3timestampTb4b4b4, Te6edf3dataTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3timestamp Tff7b72> Te6edf3fromTff7b72-Tff7b72>Te6edf3last_timestampTb4b4b4) Tb4b4b4{ T8b949e// prevent replay attacks
Tffa657uint8_t Te6edf3reply_len Tff7b72= Te6edf3handleRequestTb4b4b4(Te6edf3fromTff7b72-Tff7b72>Te6edf3isAdminTb4b4b4(Tb4b4b4) Tff7b72? T79c0ff0xFF Tff7b72: Te6edf3fromTff7b72-Tff7b72>Te6edf3permissionsTb4b4b4, Te6edf3timestampTb4b4b4, Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Tff7b72&Te6edf3dataTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4, Te6edf3len Tff7b72- T79c0ff5Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3reply_len Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72returnTb4b4b4; T8b949e// invalid command
Te6edf3fromTff7b72-Tff7b72>Te6edf3last_timestamp Tff7b72= Te6edf3timestampTb4b4b4;
Te6edf3fromTff7b72-Tff7b72>Te6edf3last_activity Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3isRouteFloodTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3path Tff7b72= Te6edf3createPathReturnTb4b4b4(Te6edf3fromTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3pathTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3path_lenTb4b4b4,
Te6edf3PAYLOAD_TYPE_RESPONSETb4b4b4, Te6edf3reply_dataTb4b4b4, Te6edf3reply_lenTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pathTb4b4b4) Te6edf3sendFloodTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3reply Tff7b72= Te6edf3createDatagramTb4b4b4(Te6edf3PAYLOAD_TYPE_RESPONSETb4b4b4, Te6edf3fromTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3reply_dataTb4b4b4, Te6edf3reply_lenTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3replyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3fromTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72!Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4) Tb4b4b4{ T8b949e// we have an out_path, so send DIRECT
Te6edf3sendDirectTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3fromTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3fromTff7b72-Tff7b72>Te6edf3out_path_lenTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sendFloodTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffonPeerDataRecv: possible replay attack detectedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3type Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_TXT_MSG Tff7b72&Tff7b72& Te6edf3len Tff7b72> T79c0ff5 Tff7b72&Tff7b72& Te6edf3fromTff7b72-Tff7b72>Te6edf3isAdminTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// a CLI command
Tffa657uint32_t Te6edf3sender_timestampTb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3sender_timestampTb4b4b4, Te6edf3dataTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// timestamp (by sender's RTC clock - which could be wrong)
Tffa657uint8_t Te6edf3flags Tff7b72= Tb4b4b4(Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72>Tff7b72> T79c0ff2Tb4b4b4)Tb4b4b4; T8b949e// message attempt number, and other flags
Tff7b72if Tb4b4b4(Te6edf3sender_timestamp Tff7b72> Te6edf3fromTff7b72-Tff7b72>Te6edf3last_timestampTb4b4b4) Tb4b4b4{ T8b949e// prevent replay attacks
Tff7b72if Tb4b4b4(Te6edf3flags Tff7b72=Tff7b72= Te6edf3TXT_TYPE_PLAINTb4b4b4) Tb4b4b4{
Tffa657bool Te6edf3handled Tff7b72= Te6edf3handleIncomingMsgTb4b4b4(Tff7b72*Te6edf3fromTb4b4b4, Te6edf3sender_timestampTb4b4b4, Tff7b72&Te6edf3dataTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4, Te6edf3flagsTb4b4b4, Te6edf3len Tff7b72- T79c0ff5Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3handledTb4b4b4) Tb4b4b4{ T8b949e// if msg was handled then send an ack
Tffa657uint32_t Te6edf3ack_hashTb4b4b4; T8b949e// calc truncated hash of the message timestamp + text + sender pub_key, to prove to sender that we got it
Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3sha256Tb4b4b4(Tb4b4b4(Tffa657uint8_t Tff7b72*Tb4b4b4) Tff7b72&Te6edf3ack_hashTb4b4b4, T79c0ff4Tb4b4b4, Te6edf3dataTb4b4b4, T79c0ff5 Tff7b72+ Te6edf3strlenTb4b4b4(Tb4b4b4(Tffa657char Tff7b72*Tb4b4b4)Tff7b72&Te6edf3dataTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3fromTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3isRouteFloodTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3path Tff7b72= Te6edf3createPathReturnTb4b4b4(Te6edf3fromTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3pathTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3path_lenTb4b4b4,
Te6edf3PAYLOAD_TYPE_ACKTb4b4b4, Tb4b4b4(Tffa657uint8_t Tff7b72*Tb4b4b4) Tff7b72&Te6edf3ack_hashTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pathTb4b4b4) Te6edf3sendFloodTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3TXT_ACK_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sendAckToTb4b4b4(Tff7b72*Te6edf3fromTb4b4b4, Te6edf3ack_hashTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3flags Tff7b72=Tff7b72= Te6edf3TXT_TYPE_CLI_DATATb4b4b4) Tb4b4b4{
Te6edf3fromTff7b72-Tff7b72>Te6edf3last_timestamp Tff7b72= Te6edf3sender_timestampTb4b4b4;
Te6edf3fromTff7b72-Tff7b72>Te6edf3last_activity Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// len can be > original length, but 'text' will be padded with zeroes
Te6edf3dataTb4b4b4[Te6edf3lenTb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; T8b949e// need to make a C string again, with null terminator
Tffa657uint8_t Te6edf3tempTb4b4b4[T79c0ff166Tb4b4b4]Tb4b4b4;
Tffa657char Tff7b72*Te6edf3command Tff7b72= Tb4b4b4(Tffa657char Tff7b72*Tb4b4b4) Tff7b72&Te6edf3dataTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4;
Tffa657char Tff7b72*Te6edf3reply Tff7b72= Tb4b4b4(Tffa657char Tff7b72*Tb4b4b4) Tff7b72&Te6edf3tempTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4;
Te6edf3handleCommandTb4b4b4(Te6edf3sender_timestampTb4b4b4, Te6edf3commandTb4b4b4, Te6edf3replyTb4b4b4)Tb4b4b4;
Tffa657int Te6edf3text_len Tff7b72= Te6edf3strlenTb4b4b4(Te6edf3replyTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3text_len Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3timestamp Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeUniqueTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3timestamp Tff7b72=Tff7b72= Te6edf3sender_timestampTb4b4b4) Tb4b4b4{
T8b949e// WORKAROUND: the two timestamps need to be different, in the CLI view
Te6edf3timestampTff7b72+Tff7b72+Tb4b4b4;
Tb4b4b4}
Te6edf3memcpyTb4b4b4(Te6edf3tempTb4b4b4, Tff7b72&Te6edf3timestampTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// mostly an extra blob to help make packet_hash unique
Te6edf3tempTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72= Tb4b4b4(Te6edf3TXT_TYPE_CLI_DATA Tff7b72<Tff7b72< T79c0ff2Tb4b4b4)Tb4b4b4;
Tff7b72auto Te6edf3reply Tff7b72= Te6edf3createDatagramTb4b4b4(Te6edf3PAYLOAD_TYPE_TXT_MSGTb4b4b4, Te6edf3fromTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3tempTb4b4b4, T79c0ff5 Tff7b72+ Te6edf3text_lenTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3replyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3fromTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72=Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4) Tb4b4b4{
Te6edf3sendFloodTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3CLI_REPLY_DELAY_MILLISTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sendDirectTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3fromTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3fromTff7b72-Tff7b72>Te6edf3out_path_lenTb4b4b4, Te6edf3CLI_REPLY_DELAY_MILLISTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffonPeerDataRecv: unsupported text type received: flags=%02xTa5d6ff"Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3flagsTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffonPeerDataRecv: possible replay attack detectedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tffa657bool Td2a8ffSensorMesh::handleIncomingMsgTb4b4b4(Te6edf3ClientInfoTff7b72& Te6edf3fromTb4b4b4, Tffa657uint32_t Te6edf3timestampTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657uint8_t Te6edf3flagsTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4) Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTTb4b4b4(Ta5d6ff"Ta5d6ffhandleIncomingMsg: unhandled msg from Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72ifdef MESH_DEBUG
Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3printHexTb4b4b4(Te6edf3SerialTb4b4b4, Te6edf3fromTb4b4b4.Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff: %sTffea00\nTa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72define CTL_TYPE_NODE_DISCOVER_REQ 0x80
Tff7b72#Tff7b72define CTL_TYPE_NODE_DISCOVER_RESP 0x90
Tffa657void Td2a8ffSensorMesh::onControlDataRecvTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3type Tff7b72= Te6edf3packetTff7b72-Tff7b72>Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72& T79c0ff0xF0Tb4b4b4; T8b949e// just test upper 4 bits
Tff7b72if Tb4b4b4(Te6edf3type Tff7b72=Tff7b72= Te6edf3CTL_TYPE_NODE_DISCOVER_REQ Tff7b72&Tff7b72& Te6edf3packetTff7b72-Tff7b72>Te6edf3payload_len Tff7b72>Tff7b72= T79c0ff6Tb4b4b4) Tb4b4b4{
T8b949e// TODO: apply rate limiting to these!
Tffa657int Te6edf3i Tff7b72= T79c0ff1Tb4b4b4;
Tffa657uint8_t Te6edf3filter Tff7b72= Te6edf3packetTff7b72-Tff7b72>Te6edf3payloadTb4b4b4[Te6edf3iTff7b72+Tff7b72+Tb4b4b4]Tb4b4b4;
Tffa657uint32_t Te6edf3tagTb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3tagTb4b4b4, Tff7b72&Te6edf3packetTff7b72-Tff7b72>Te6edf3payloadTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; Te6edf3i Tff7b72+Tff7b72= T79c0ff4Tb4b4b4;
Tffa657uint32_t Te6edf3sinceTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3payload_len Tff7b72>Tff7b72= Te6edf3iTff7b72+T79c0ff4Tb4b4b4) Tb4b4b4{ T8b949e// optional since field
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3sinceTb4b4b4, Tff7b72&Te6edf3packetTff7b72-Tff7b72>Te6edf3payloadTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; Te6edf3i Tff7b72+Tff7b72= T79c0ff4Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3since Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tb4b4b4(Te6edf3filter Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<Tff7b72< Te6edf3ADV_TYPE_SENSORTb4b4b4)Tb4b4b4) Tff7b72!Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3_prefsTb4b4b4.Te6edf3discovery_mod_timestamp Tff7b72>Tff7b72= Te6edf3sinceTb4b4b4) Tb4b4b4{
Tffa657bool Te6edf3prefix_only Tff7b72= Te6edf3packetTff7b72-Tff7b72>Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72& T79c0ff1Tb4b4b4;
Tffa657uint8_t Te6edf3dataTb4b4b4[T79c0ff6 Tff7b72+ Te6edf3PUB_KEY_SIZETb4b4b4]Tb4b4b4;
Te6edf3dataTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72= Te6edf3CTL_TYPE_NODE_DISCOVER_RESP Tff7b72| Te6edf3ADV_TYPE_SENSORTb4b4b4; T8b949e// low 4-bits for node type
Te6edf3dataTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72= Te6edf3packetTff7b72-Tff7b72>Te6edf3_snrTb4b4b4; T8b949e// let sender know the inbound SNR ( x 4)
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3dataTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4, Tff7b72&Te6edf3tagTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// include tag from request, for client to match to
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3dataTb4b4b4[T79c0ff6Tb4b4b4]Tb4b4b4, Te6edf3self_idTb4b4b4.Te6edf3pub_keyTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Tff7b72auto Te6edf3resp Tff7b72= Te6edf3createControlDataTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3prefix_only Tff7b72? T79c0ff6 Tff7b72+ T79c0ff8 Tff7b72: T79c0ff6 Tff7b72+ Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3respTb4b4b4) Tb4b4b4{
Te6edf3sendZeroHopTb4b4b4(Te6edf3respTb4b4b4, Te6edf3getRetransmitDelayTb4b4b4(Te6edf3respTb4b4b4)Tff7b72*T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// apply random delay (widened x4), as multiple nodes can respond to this
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tffa657bool Td2a8ffSensorMesh::onPeerPathRecvTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657int Te6edf3sender_idxTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3pathTb4b4b4, Tffa657uint8_t Te6edf3path_lenTb4b4b4, Tffa657uint8_t Te6edf3extra_typeTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3extraTb4b4b4, Tffa657uint8_t Te6edf3extra_lenTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3i Tff7b72= Te6edf3matching_peer_indexesTb4b4b4[Te6edf3sender_idxTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3i Tff7b72< T79c0ff0 Tff7b72|Tff7b72| Te6edf3i Tff7b72>Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffonPeerPathRecv: Invalid sender idx: %dTa5d6ff"Tb4b4b4, Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Te6edf3ClientInfoTff7b72* Te6edf3from Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffPATH to contact, path_len=%dTa5d6ff"Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4) Te6edf3path_lenTb4b4b4)Tb4b4b4;
T8b949e// NOTE: for this impl, we just replace the current 'out_path' regardless, whenever sender sends us a new out_path.
T8b949e// FUTURE: could store multiple out_paths per contact, and try to find which is the 'best'(?)
Te6edf3fromTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72= Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72:Tff7b72:Te6edf3copyPathTb4b4b4(Te6edf3fromTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3pathTb4b4b4, Te6edf3path_lenTb4b4b4)Tb4b4b4; T8b949e// store a copy of path, for sendDirect()
Te6edf3fromTff7b72-Tff7b72>Te6edf3last_activity Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// REVISIT: maybe make ALL out_paths non-persisted to minimise flash writes??
Tff7b72if Tb4b4b4(Te6edf3fromTff7b72-Tff7b72>Te6edf3isAdminTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// only do saveContacts() (of this out_path change) if this is an admin
Te6edf3dirty_contacts_expiry Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3LAZY_CONTACTS_WRITE_DELAYTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// NOTE: no reciprocal path send!!
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tffa657void Td2a8ffSensorMesh::onAckRecvTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint32_t Te6edf3ack_crcTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3num_alert_tasks Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3t Tff7b72= Te6edf3alert_tasksTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4; T8b949e// check current alert task
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3tTff7b72-Tff7b72>Te6edf3attemptTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ack_crc Tff7b72=Tff7b72= Te6edf3tTff7b72-Tff7b72>Te6edf3expected_acksTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4) Tb4b4b4{ T8b949e// matching ACK!
Te6edf3tTff7b72-Tff7b72>Te6edf3attempt Tff7b72= T79c0ff4Tb4b4b4; T8b949e// signal to move to next contact
Te6edf3tTff7b72-Tff7b72>Te6edf3send_expiry Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3packetTff7b72-Tff7b72>Te6edf3markDoNotRetransmitTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// ACK was for this node, so don't retransmit
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3SensorMeshTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3MainBoardTff7b72& Te6edf3boardTb4b4b4, Te6edf3meshTff7b72:Tff7b72:Te6edf3RadioTff7b72& Te6edf3radioTb4b4b4, Te6edf3meshTff7b72:Tff7b72:Te6edf3MillisecondClockTff7b72& Te6edf3msTb4b4b4, Te6edf3meshTff7b72:Tff7b72:Te6edf3RNGTff7b72& Te6edf3rngTb4b4b4, Te6edf3meshTff7b72:Tff7b72:Te6edf3RTCClockTff7b72& Te6edf3rtcTb4b4b4, Te6edf3meshTff7b72:Tff7b72:Te6edf3MeshTablesTff7b72& Te6edf3tablesTb4b4b4)
Tff7b72: Te6edf3meshTff7b72:Tff7b72:Te6edf3MeshTb4b4b4(Te6edf3radioTb4b4b4, Te6edf3msTb4b4b4, Te6edf3rngTb4b4b4, Te6edf3rtcTb4b4b4, Tff7b72*Tff7b72new Te6edf3StaticPoolPacketManagerTb4b4b4(T79c0ff32Tb4b4b4)Tb4b4b4, Te6edf3tablesTb4b4b4)Tb4b4b4,
Te6edf3region_mapTb4b4b4(Te6edf3key_storeTb4b4b4)Tb4b4b4,
Te6edf3_cliTb4b4b4(Te6edf3boardTb4b4b4, Te6edf3rtcTb4b4b4, Te6edf3sensorsTb4b4b4, Te6edf3region_mapTb4b4b4, Te6edf3aclTb4b4b4, Tff7b72&Te6edf3_prefsTb4b4b4, Tff7b72thisTb4b4b4)Tb4b4b4,
Te6edf3telemetryTb4b4b4(Te6edf3MAX_PACKET_PAYLOAD Tff7b72- T79c0ff4Tb4b4b4)
Tb4b4b4{
Te6edf3next_local_advert Tff7b72= Te6edf3next_flood_advert Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3dirty_contacts_expiry Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3last_read_time Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3num_alert_tasks Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3set_radio_at Tff7b72= Te6edf3revert_radio_at Tff7b72= T79c0ff0Tb4b4b4;
T8b949e// defaults
Te6edf3_prefsTb4b4b4.Te6edf3airtime_factor Tff7b72= T79c0ff1.0Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3rx_delay_base Tff7b72= T79c0ff0.0fTb4b4b4; T8b949e// turn off by default, was 10.0;
Te6edf3_prefsTb4b4b4.Te6edf3tx_delay_factor Tff7b72= T79c0ff0.5fTb4b4b4; T8b949e// was 0.25f
Te6edf3_prefsTb4b4b4.Te6edf3direct_tx_delay_factor Tff7b72= T79c0ff0.2fTb4b4b4; T8b949e// was zero
Te6edf3StrHelperTff7b72:Tff7b72:Te6edf3strncpyTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3node_nameTb4b4b4, Te6edf3ADVERT_NAMETb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3node_nameTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3node_lat Tff7b72= Te6edf3ADVERT_LATTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3node_lon Tff7b72= Te6edf3ADVERT_LONTb4b4b4;
Te6edf3StrHelperTff7b72:Tff7b72:Te6edf3strncpyTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3passwordTb4b4b4, Te6edf3ADMIN_PASSWORDTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3passwordTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3freq Tff7b72= Te6edf3LORA_FREQTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3sf Tff7b72= Te6edf3LORA_SFTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3bw Tff7b72= Te6edf3LORA_BWTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3cr Tff7b72= Te6edf3LORA_CRTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3tx_power_dbm Tff7b72= Te6edf3LORA_TX_POWERTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3advert_interval Tff7b72= T79c0ff1Tb4b4b4; T8b949e// default to 2 minutes for NEW installs
Te6edf3_prefsTb4b4b4.Te6edf3flood_advert_interval Tff7b72= T79c0ff0Tb4b4b4; T8b949e// disabled
Te6edf3_prefsTb4b4b4.Te6edf3disable_fwd Tff7b72= Tffa657trueTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3flood_max Tff7b72= T79c0ff64Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3interference_threshold Tff7b72= T79c0ff0Tb4b4b4; T8b949e// disabled
Te6edf3_prefsTb4b4b4.Te6edf3cad_enabled Tff7b72= T79c0ff0Tb4b4b4; T8b949e// hardware CAD before TX (off by default; 'set cad on')
T8b949e// GPS defaults
Te6edf3_prefsTb4b4b4.Te6edf3gps_enabled Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3gps_interval Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3advert_loc_policy Tff7b72= Te6edf3ADVERT_LOC_PREFSTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3radio_fem_rxgain Tff7b72= T79c0ff1Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3radio_fem_txgain Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3memsetTb4b4b4(Te6edf3default_scopeTb4b4b4.Te6edf3keyTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3default_scopeTb4b4b4.Te6edf3keyTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3beginTb4b4b4(Te6edf3FILESYSTEMTff7b72* Te6edf3fsTb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3MeshTff7b72:Tff7b72:Te6edf3beginTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3_fs Tff7b72= Te6edf3fsTb4b4b4;
T8b949e// load persisted prefs
Te6edf3_cliTb4b4b4.Te6edf3loadPrefsTb4b4b4(Te6edf3_fsTb4b4b4)Tb4b4b4;
Te6edf3aclTb4b4b4.Te6edf3loadTb4b4b4(Te6edf3_fsTb4b4b4, Te6edf3self_idTb4b4b4)Tb4b4b4;
Te6edf3region_mapTb4b4b4.Te6edf3loadTb4b4b4(Te6edf3_fsTb4b4b4)Tb4b4b4;
T8b949e// establish default-scope
Tb4b4b4{
Te6edf3RegionEntryTff7b72* Te6edf3r Tff7b72= Te6edf3region_mapTb4b4b4.Te6edf3getDefaultRegionTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rTb4b4b4) Tb4b4b4{
Te6edf3region_mapTb4b4b4.Te6edf3getTransportKeysForTb4b4b4(Tff7b72*Te6edf3rTb4b4b4, Tff7b72&Te6edf3default_scopeTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72#Tff7b72ifdef DEFAULT_FLOOD_SCOPE_NAME
Te6edf3r Tff7b72= Te6edf3region_mapTb4b4b4.Te6edf3findByNameTb4b4b4(Te6edf3DEFAULT_FLOOD_SCOPE_NAMETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3r Tff7b72=Tff7b72= Tffa657NULLTb4b4b4) Tb4b4b4{
Te6edf3r Tff7b72= Te6edf3region_mapTb4b4b4.Te6edf3putRegionTb4b4b4(Te6edf3DEFAULT_FLOOD_SCOPE_NAMETb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4; T8b949e// auto-create the default scope region
Tff7b72if Tb4b4b4(Te6edf3rTb4b4b4) Tb4b4b4{ Te6edf3rTff7b72-Tff7b72>Te6edf3flags Tff7b72= T79c0ff0Tb4b4b4; Tb4b4b4} T8b949e// Allow-flood
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3rTb4b4b4) Tb4b4b4{
Te6edf3region_mapTb4b4b4.Te6edf3setDefaultRegionTb4b4b4(Te6edf3rTb4b4b4)Tb4b4b4;
Te6edf3region_mapTb4b4b4.Te6edf3getTransportKeysForTb4b4b4(Tff7b72*Te6edf3rTb4b4b4, Tff7b72&Te6edf3default_scopeTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}
Te6edf3radio_driverTb4b4b4.Te6edf3setParamsTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3freqTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3bwTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3sfTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3crTb4b4b4)Tb4b4b4;
Te6edf3radio_driverTb4b4b4.Te6edf3setTxPowerTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3tx_power_dbmTb4b4b4)Tb4b4b4;
Te6edf3boardTb4b4b4.Te6edf3setLoRaFemLnaEnabledTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3radio_fem_rxgainTb4b4b4)Tb4b4b4;
Te6edf3boardTb4b4b4.Te6edf3setLoRaFemPaGainEnabledTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3radio_fem_txgainTb4b4b4)Tb4b4b4;
Te6edf3updateAdvertTimerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3updateFloodAdvertTimerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3boardTb4b4b4.Te6edf3setAdcMultiplierTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3adc_multiplierTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if ENV_INCLUDE_GPS == 1
Te6edf3applyGpsPrefsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tffa657bool Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3formatFileSystemTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
Tff7b72return Te6edf3InternalFSTb4b4b4.Te6edf3formatTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(RP2040_PLATFORM)
Tff7b72return Te6edf3LittleFSTb4b4b4.Te6edf3formatTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(ESP32)
Tff7b72return Te6edf3SPIFFSTb4b4b4.Te6edf3formatTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72#Tff7b72error "need to implement file system erase"
Tff7b72return Tffa657falseTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3saveIdentityTb4b4b4(Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3LocalIdentityTff7b72& Te6edf3new_idTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
Te6edf3IdentityStore Te6edf3storeTb4b4b4(Tff7b72*Te6edf3_fsTb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(ESP32)
Te6edf3IdentityStore Te6edf3storeTb4b4b4(Tff7b72*Te6edf3_fsTb4b4b4, Ta5d6ff"Ta5d6ff/identityTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(RP2040_PLATFORM)
Te6edf3IdentityStore Te6edf3storeTb4b4b4(Tff7b72*Te6edf3_fsTb4b4b4, Ta5d6ff"Ta5d6ff/identityTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72#Tff7b72error "need to define saveIdentity()"
Tff7b72#Tff7b72endif
Te6edf3storeTb4b4b4.Te6edf3saveTb4b4b4(Ta5d6ff"Ta5d6ff_mainTa5d6ff"Tb4b4b4, Te6edf3new_idTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3applyTempRadioParamsTb4b4b4(Tffa657float Te6edf3freqTb4b4b4, Tffa657float Te6edf3bwTb4b4b4, Tffa657uint8_t Te6edf3sfTb4b4b4, Tffa657uint8_t Te6edf3crTb4b4b4, Tffa657int Te6edf3timeout_minsTb4b4b4) Tb4b4b4{
Te6edf3set_radio_at Tff7b72= Te6edf3futureMillisTb4b4b4(T79c0ff2000Tb4b4b4)Tb4b4b4; T8b949e// give CLI reply some time to be sent back, before applying temp radio params
Te6edf3pending_freq Tff7b72= Te6edf3freqTb4b4b4;
Te6edf3pending_bw Tff7b72= Te6edf3bwTb4b4b4;
Te6edf3pending_sf Tff7b72= Te6edf3sfTb4b4b4;
Te6edf3pending_cr Tff7b72= Te6edf3crTb4b4b4;
Te6edf3revert_radio_at Tff7b72= Te6edf3futureMillisTb4b4b4(T79c0ff2000 Tff7b72+ Te6edf3timeout_minsTff7b72*T79c0ff60Tff7b72*T79c0ff1000Tb4b4b4)Tb4b4b4; T8b949e// schedule when to revert radio params
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3sendSelfAdvertisementTb4b4b4(Tffa657int Te6edf3delay_millisTb4b4b4, Tffa657bool Te6edf3floodTb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3pkt Tff7b72= Te6edf3createSelfAdvertTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pktTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3floodTb4b4b4) Tb4b4b4{
Te6edf3sendFloodTb4b4b4(Te6edf3pktTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3path_hash_mode Tff7b72+ T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sendZeroHopTb4b4b4(Te6edf3pktTb4b4b4, Te6edf3delay_millisTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffERROR: unable to create advertisement packet!Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3updateAdvertTimerTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3advert_interval Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// schedule local advert timer
Te6edf3next_local_advert Tff7b72= Te6edf3futureMillisTb4b4b4( Tb4b4b4(Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3_prefsTb4b4b4.Te6edf3advert_intervalTb4b4b4) Tff7b72* T79c0ff2 Tff7b72* T79c0ff60 Tff7b72* T79c0ff1000Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3next_local_advert Tff7b72= T79c0ff0Tb4b4b4; T8b949e// stop the timer
Tb4b4b4}
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3updateFloodAdvertTimerTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3flood_advert_interval Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// schedule flood advert timer
Te6edf3next_flood_advert Tff7b72= Te6edf3futureMillisTb4b4b4( Tb4b4b4(Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3_prefsTb4b4b4.Te6edf3flood_advert_intervalTb4b4b4) Tff7b72* T79c0ff60 Tff7b72* T79c0ff60 Tff7b72* T79c0ff1000Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3next_flood_advert Tff7b72= T79c0ff0Tb4b4b4; T8b949e// stop the timer
Tb4b4b4}
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3setTxPowerTb4b4b4(Tffa657int8_t Te6edf3power_dbmTb4b4b4) Tb4b4b4{
Te6edf3radio_driverTb4b4b4.Te6edf3setTxPowerTb4b4b4(Te6edf3power_dbmTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3formatStatsReplyTb4b4b4(Tffa657char Tff7b72*Te6edf3replyTb4b4b4) Tb4b4b4{
Te6edf3StatsFormatHelperTff7b72:Tff7b72:Te6edf3formatCoreStatsTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3boardTb4b4b4, Tff7b72*Te6edf3_msTb4b4b4, Te6edf3_err_flagsTb4b4b4, Te6edf3_mgrTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3formatRadioStatsReplyTb4b4b4(Tffa657char Tff7b72*Te6edf3replyTb4b4b4) Tb4b4b4{
Te6edf3StatsFormatHelperTff7b72:Tff7b72:Te6edf3formatRadioStatsTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3_radioTb4b4b4, Te6edf3radio_driverTb4b4b4, Te6edf3getTotalAirTimeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3getReceiveAirTimeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3formatPacketStatsReplyTb4b4b4(Tffa657char Tff7b72*Te6edf3replyTb4b4b4) Tb4b4b4{
Te6edf3StatsFormatHelperTff7b72:Tff7b72:Te6edf3formatPacketStatsTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3radio_driverTb4b4b4, Te6edf3getNumSentFloodTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3getNumSentDirectTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3getNumRecvFloodTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3getNumRecvDirectTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657float Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3getTelemValueTb4b4b4(Tffa657uint8_t Te6edf3channelTb4b4b4, Tffa657uint8_t Te6edf3typeTb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3buf Tff7b72= Te6edf3telemetryTb4b4b4.Te6edf3getBufferTb4b4b4(Tb4b4b4)Tb4b4b4;
Tffa657uint8_t Te6edf3size Tff7b72= Te6edf3telemetryTb4b4b4.Te6edf3getSizeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tffa657uint8_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3i Tff7b72+ T79c0ff2 Tff7b72< Te6edf3sizeTb4b4b4) Tb4b4b4{
T8b949e// Get channel #
Tffa657uint8_t Te6edf3ch Tff7b72= Te6edf3bufTb4b4b4[Te6edf3iTff7b72+Tff7b72+Tb4b4b4]Tb4b4b4;
T8b949e// Get data type
Tffa657uint8_t Te6edf3t Tff7b72= Te6edf3bufTb4b4b4[Te6edf3iTff7b72+Tff7b72+Tb4b4b4]Tb4b4b4;
Tffa657uint8_t Te6edf3sz Tff7b72= Te6edf3getDataSizeTb4b4b4(Te6edf3tTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3ch Tff7b72=Tff7b72= Te6edf3channel Tff7b72&Tff7b72& Te6edf3t Tff7b72=Tff7b72= Te6edf3typeTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3getFloatTb4b4b4(Tff7b72&Te6edf3bufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4, Te6edf3szTb4b4b4, Te6edf3getMultiplierTb4b4b4(Te6edf3tTb4b4b4)Tb4b4b4, Te6edf3isSignedTb4b4b4(Te6edf3tTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3i Tff7b72+Tff7b72= Te6edf3szTb4b4b4; T8b949e// skip
Tb4b4b4}
Tff7b72return T79c0ff0.0fTb4b4b4; T8b949e// not found
Tb4b4b4}
Tffa657bool Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3getGPSTb4b4b4(Tffa657uint8_t Te6edf3channelTb4b4b4, Tffa657floatTff7b72& Te6edf3latTb4b4b4, Tffa657floatTff7b72& Te6edf3lonTb4b4b4, Tffa657floatTff7b72& Te6edf3altTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3channel Tff7b72=Tff7b72= Te6edf3TELEM_CHANNEL_SELFTb4b4b4) Tb4b4b4{
Te6edf3lat Tff7b72= Te6edf3sensorsTb4b4b4.Te6edf3node_latTb4b4b4;
Te6edf3lon Tff7b72= Te6edf3sensorsTb4b4b4.Te6edf3node_lonTb4b4b4;
Te6edf3alt Tff7b72= Te6edf3sensorsTb4b4b4.Te6edf3node_altitudeTb4b4b4;
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}
T8b949e// REVISIT: custom GPS channels??
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tffa657void Te6edf3SensorMeshTff7b72:Tff7b72:Te6edf3loopTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3MeshTff7b72:Tff7b72:Te6edf3loopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3next_flood_advert Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3next_flood_advertTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3pkt Tff7b72= Te6edf3createSelfAdvertTb4b4b4(Tb4b4b4)Tb4b4b4;
Tffa657unsigned Tffa657long Te6edf3delay_millis Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pktTb4b4b4) Te6edf3sendFloodTb4b4b4(Te6edf3pktTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3path_hash_mode Tff7b72+ T79c0ff1Tb4b4b4)Tb4b4b4;
Te6edf3updateFloodAdvertTimerTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// schedule next flood advert
Te6edf3updateAdvertTimerTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// also schedule local advert (so they don't overlap)
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3next_local_advert Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3next_local_advertTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3pkt Tff7b72= Te6edf3createSelfAdvertTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pktTb4b4b4) Te6edf3sendZeroHopTb4b4b4(Te6edf3pktTb4b4b4)Tb4b4b4;
Te6edf3updateAdvertTimerTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// schedule next local advert
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3set_radio_at Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3set_radio_atTb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// apply pending (temporary) radio params
Te6edf3set_radio_at Tff7b72= T79c0ff0Tb4b4b4; T8b949e// clear timer
Te6edf3radio_driverTb4b4b4.Te6edf3setParamsTb4b4b4(Te6edf3pending_freqTb4b4b4, Te6edf3pending_bwTb4b4b4, Te6edf3pending_sfTb4b4b4, Te6edf3pending_crTb4b4b4)Tb4b4b4;
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffTemp radio paramsTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3revert_radio_at Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3revert_radio_atTb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// revert radio params to orig
Te6edf3revert_radio_at Tff7b72= T79c0ff0Tb4b4b4; T8b949e// clear timer
Te6edf3radio_driverTb4b4b4.Te6edf3setParamsTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3freqTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3bwTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3sfTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3crTb4b4b4)Tb4b4b4;
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffRadio params restoredTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657uint32_t Te6edf3curr Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3curr Tff7b72>Tff7b72= Te6edf3last_read_time Tff7b72+ Te6edf3SENSOR_READ_INTERVAL_SECSTb4b4b4) Tb4b4b4{
Te6edf3telemetryTb4b4b4.Te6edf3resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3telemetryTb4b4b4.Te6edf3addVoltageTb4b4b4(Te6edf3TELEM_CHANNEL_SELFTb4b4b4, Tb4b4b4(Tffa657floatTb4b4b4)Te6edf3boardTb4b4b4.Te6edf3getBattMilliVoltsTb4b4b4(Tb4b4b4) Tff7b72/ T79c0ff1000.0fTb4b4b4)Tb4b4b4;
T8b949e// query other sensors -- target specific
Te6edf3sensorsTb4b4b4.Te6edf3querySensorsTb4b4b4(T79c0ff0xFFTb4b4b4, Te6edf3telemetryTb4b4b4)Tb4b4b4; T8b949e// allow all telemetry permissions
Te6edf3onSensorDataReadTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_read_time Tff7b72= Te6edf3currTb4b4b4;
Tb4b4b4}
T8b949e// check the alert send queue
Tff7b72if Tb4b4b4(Te6edf3num_alert_tasks Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3t Tff7b72= Te6edf3alert_tasksTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4; T8b949e// process head of queue
Tff7b72if Tb4b4b4(Te6edf3millisHasNowPassedTb4b4b4(Te6edf3tTff7b72-Tff7b72>Te6edf3send_expiryTb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// next send needed?
Tff7b72if Tb4b4b4(Te6edf3tTff7b72-Tff7b72>Te6edf3attempt Tff7b72>Tff7b72= T79c0ff4Tb4b4b4) Tb4b4b4{ T8b949e// max attempts reached, try next contact
Te6edf3tTff7b72-Tff7b72>Te6edf3curr_contact_idxTff7b72+Tff7b72+Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tTff7b72-Tff7b72>Te6edf3curr_contact_idx Tff7b72>Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// no more contacts to try?
Te6edf3num_alert_tasksTff7b72-Tff7b72-Tb4b4b4; T8b949e// remove t from queue
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3num_alert_tasksTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Te6edf3alert_tasksTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Te6edf3alert_tasksTb4b4b4[Te6edf3i Tff7b72+ T79c0ff1Tb4b4b4]Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72auto Te6edf3c Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3tTff7b72-Tff7b72>Te6edf3curr_contact_idxTb4b4b4)Tb4b4b4;
Tffa657uint16_t Te6edf3pri_mask Tff7b72= Tb4b4b4(Te6edf3tTff7b72-Tff7b72>Te6edf3pri Tff7b72=Tff7b72= Te6edf3HIGH_PRI_ALERTTb4b4b4) Tff7b72? Te6edf3PERM_RECV_ALERTS_HI Tff7b72: Te6edf3PERM_RECV_ALERTS_LOTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cTff7b72-Tff7b72>Te6edf3permissions Tff7b72& Te6edf3pri_maskTb4b4b4) Tb4b4b4{ T8b949e// contact wants alert
T8b949e// reset attempts
Te6edf3tTff7b72-Tff7b72>Te6edf3attempt Tff7b72= Tb4b4b4(Te6edf3tTff7b72-Tff7b72>Te6edf3pri Tff7b72=Tff7b72= Te6edf3LOW_PRI_ALERTTb4b4b4) Tff7b72? T79c0ff3 Tff7b72: T79c0ff0Tb4b4b4; T8b949e// Low pri alerts, start at attempt #3 (ie. only make ONE attempt)
Te6edf3tTff7b72-Tff7b72>Te6edf3timestamp Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeUniqueTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// need unique timestamp per contact
Te6edf3sendAlertTb4b4b4(Te6edf3cTb4b4b4, Te6edf3tTb4b4b4)Tb4b4b4; T8b949e// NOTE: modifies attempt, expected_acks[] and send_expiry
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// next contact tested in next ::loop()
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3tTff7b72-Tff7b72>Te6edf3curr_contact_idx Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3c Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3tTff7b72-Tff7b72>Te6edf3curr_contact_idxTb4b4b4)Tb4b4b4; T8b949e// send next attempt
Te6edf3sendAlertTb4b4b4(Te6edf3cTb4b4b4, Te6edf3tTb4b4b4)Tb4b4b4; T8b949e// NOTE: modifies attempt, expected_acks[] and send_expiry
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// contact list has likely been modified while waiting for alert ACK, cancel this task
Te6edf3tTff7b72-Tff7b72>Te6edf3attempt Tff7b72= T79c0ff4Tb4b4b4; T8b949e// next ::loop() will remove t from queue
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e// is there are pending dirty contacts write needed?
Tff7b72if Tb4b4b4(Te6edf3dirty_contacts_expiry Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3dirty_contacts_expiryTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3aclTb4b4b4.Te6edf3saveTb4b4b4(Te6edf3_fsTb4b4b4)Tb4b4b4;
Te6edf3dirty_contacts_expiry Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.36s